//
// Created by cnsunrun on 2018/3/26.
//

#include <jni.h>
#include <string.h>
#include <malloc.h>
#include "app-const.h"
#include <Android/log.h>
#include "app-utils.h"
#include <arpa/inet.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <unistd.h>
#include <netdb.h>

#define TAG "app-net-log" // 这个是自定义的LOG的标识
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,TAG ,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__)
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,TAG ,__VA_ARGS__)
#ifndef APIEXERCISE_APP_UTILS_H
#define APIEXERCISE_APP_UTILS_H
#endif //APIEXERCISE_APP_UTILS_H
#define BUFFER_SIZE 2
#define NET_Header_ID (0x7F)
#define NET_Header_VER (0x01)
#define NET_MAX_PACKET_SIZE (4096)
# define NET_AUTHSERVER_ADDR "192.168.108.181"
# define NET_AUTHSERVER_PORT (33880)

#define NET_TOKEN_SIZE (16)
#define NET_UUID_SIZE (16)
typedef unsigned char UInt8;

// 数据头
typedef struct {
    UInt8 head4[4]; // index 0: NET_Header_ID; index 1: NET_Header_VER; 2:插件号 ;3:命令字
    int dataLen;
} t_net_header;


// 通信错误码定义
#define SUCCESS 0

// socket 相关错误码
#define INVALID_SOCKET (~0)

#define NET_SOCKET_ERROR -1
#define NET_CONNNECT_TIMEOUT -100
#define NET_RECV_TIMEOUT -200
#define NET_COMMUNICATOR_ERROR -500



/**
 * 感谢大风提供的三个发送或处理请求的方法
 * @edited fred
 */

int Connect(int *sock, const char *address, unsigned short port) {
    int _sk = socket(AF_INET, SOCK_STREAM, 0);
    if (_sk == INVALID_SOCKET)
        return NET_SOCKET_ERROR;
    struct sockaddr_in sockAddr;
    memset(&sockAddr, 0, sizeof(sockAddr));

    sockAddr.sin_family = AF_INET;
    sockAddr.sin_addr.s_addr = inet_addr(address);
    sockAddr.sin_port = htons(port);

    if (sockAddr.sin_addr.s_addr == INADDR_NONE) {
        struct hostent *host = gethostbyname(address);
        if (host == NULL) {
            return NET_SOCKET_ERROR;
        }
        sockAddr.sin_addr.s_addr = ((struct in_addr *) host->h_addr)->s_addr;
    }
    fcntl(_sk, F_SETFL, O_NONBLOCK | fcntl(_sk, F_GETFL)); // 设置成非阻塞
    int ret = connect(_sk, (struct sockaddr *) &sockAddr, sizeof(struct sockaddr));

    fd_set fdset;
    struct timeval tmv;
    FD_ZERO(&fdset);
    FD_SET(_sk, &fdset);
    tmv.tv_sec = 15; // 设置超时时间
    tmv.tv_usec = 0;

    ret = select(_sk + 1, 0, &fdset, 0, &tmv);
    if (ret == 0) {
        return NET_CONNNECT_TIMEOUT;
    }
    else if (ret < 0) {
        return NET_SOCKET_ERROR;
    }
    int flags = fcntl(_sk, F_GETFL, 0);
    flags &= ~O_NONBLOCK;
    fcntl(_sk, F_SETFL, flags); // 设置成阻塞
    *sock = _sk;
    return SUCCESS;
}

int SendData(int _sk, const char *buffer, int bufferSize) {
    int ret = send(_sk, buffer, bufferSize, 0);
    if (ret != bufferSize)
        return NET_SOCKET_ERROR;
    return SUCCESS;
}

 int ReceiveData(int _sk,void* buffer){
     return recv(_sk,buffer, sizeof(buffer),0);
}

int DisConnect(int _sk) {
    if (_sk != INVALID_SOCKET) {
        close(_sk);
        _sk = INVALID_SOCKET;
    }
    return SUCCESS;
}

//    signal(SIGPIPE,SIG_IGN);//自己可以处理一些信号
void request(char *host, int port, char *reqHead) {

    int sk = INVALID_SOCKET;
    int ret = Connect(&sk, host, port);
    if (ret != SUCCESS)
        return;
    ret = SendData(sk, reqHead, strlen(reqHead));
    LOGI("SendData TRACE");
    if (ret != SUCCESS) {
        LOGI("send data error");
        return;
    }
    LOGI("send data success");
    DisConnect(sk);
    LOGI("DisConnect");
    //后续处理返回的数据即可 由于本功能不需要 so省略
}


typedef struct paraStruct {
    char *watch_path;
    char *cpath;
    char *chost;
    char *para;
    char *method;
    int cport;
} paraStruct;

int httpRequester(paraStruct *data) {
    char s[2048] = {0};
    LOGI("c-code::method=%s",data->method);
    if (strcmp(data->method, "POST") == 0) {
        sprintf(s,
                "POST %s HTTP/1.1\r\nHost: %s\r\nCache-Control: no-cache\r\nContent-Length: %d\r\nContent-Type: application/x-www-form-urlencoded\r\n\r\n%s",
                data->cpath, data->chost, strlen(data->para), data->para);
    }
    else if (strcmp(data->method, "GET") == 0) {
        sprintf(s,
                "GET %s HTTP/1.1\r\nHost: %s\r\nCache-Control: no-cache\r\nContent-Type: application/x-www-form-urlencoded\r\n\r\n",
                data->cpath, data->chost);

    } else {
        return 1;
    }
    request(data->chost, data->cport, s);
    return 0;
}






